package com.spzx.payment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.rabbit.constant.MqConst;
import com.spzx.common.rabbit.service.RabbitService;
import com.spzx.order.api.RemoteOrderInfoService;
import com.spzx.order.domain.OrderInfo;
import com.spzx.payment.domain.PaymentInfo;
import com.spzx.payment.mapper.PaymentInfoMapper;
import com.spzx.payment.service.PaymentInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.intellij.lang.annotations.MagicConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

/**
 * <p>
 * 付款信息表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2025-05-10
 */
@Service
@Slf4j
public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfo> implements PaymentInfoService {

    @Autowired
    private RemoteOrderInfoService remoteOrderInfoService;

    @Autowired
    private RabbitService rabbitService;


    /**
     * 保存本地交易记录信息
     *
     * @param orderNo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentInfo savePaymentInfo(String orderNo) {
        //1.根据订单编号查询本地记录记录,存在则返回
        PaymentInfo paymentInfo = this.getOne(
                new LambdaQueryWrapper<PaymentInfo>()
                        .eq(PaymentInfo::getOrderNo, orderNo)
        );
        if (paymentInfo != null) {
            return paymentInfo;
        }
        //2.构建本地交易记录对象 paymentInfo
        PaymentInfo paymentInfo1 = new PaymentInfo();
        paymentInfo1.setCreateBy(SecurityContextHolder.getUserName());
        paymentInfo1.setUserId(SecurityContextHolder.getUserId());
        paymentInfo1.setOrderNo(orderNo);
        paymentInfo1.setPayType(2);
        //3.根据订单编号远程调用订单服务获取订单及订单明细信息
        R<OrderInfo> r = remoteOrderInfoService.getByOrderNo(orderNo, SecurityConstants.INNER);
        if (R.FAIL == r.getCode()) {
            throw new RuntimeException("远程调用订单服务失败，原因：" + r.getMsg());
        }
        OrderInfo orderInfo = r.getData();
        //4. 判断订单状态，如果是已支付或者已关闭，则直接返回
        if (orderInfo.getOrderStatus() != 0) {
            throw new RuntimeException("订单状态异常，不能进行支付");
        }
        paymentInfo1.setAmount(orderInfo.getTotalAmount());
        paymentInfo1.setContent(orderInfo.getOrderItemList().get(0).getSkuName());
        paymentInfo1.setPaymentStatus("0");

        //TODO 支付宝端交易编号、回调时间、回调内容 等 用户付款成功，支付宝会回调商户系统再更新三个字段
        //paymentInfo1.setTradeNo();
        //paymentInfo1.setCallbackTime();
        //paymentInfo1.setCallbackContent();

        //4.保存本地交易记录
        this.save(paymentInfo1);
        return paymentInfo1;
    }

    /**
     * 用户付款成功后，更新本地交易记录
     *
     * @param paramMap
     */
    @Override
    public void updatePaymentStatus(Map<String, String> paramMap) {
        //1.根据订单编号查询本地交易记录 验证：用户实付金额跟商户侧应付金额是否一致
        String orderNo = paramMap.get("out_trade_no");
        PaymentInfo paymentInfo = this.getOne(
                new LambdaQueryWrapper<PaymentInfo>()
                        .eq(PaymentInfo::getOrderNo, orderNo)
        );
        String buyerPayAmount = paramMap.get("buyer_pay_amount");
        if (paymentInfo.getAmount().compareTo(new BigDecimal(buyerPayAmount)) != 0) {
            log.error("该笔订单实付金额与交易记录金额不一致，订单编号：{}", orderNo);
            throw new RuntimeException("该笔订单实付金额与交易记录金额不一致，订单编号：" + orderNo);
        }
        //2.更新本地交易记录：状态：已支付、支付宝订单号、回调时间、回调内容
        paymentInfo.setPaymentStatus("1");
        paymentInfo.setTradeNo(paramMap.get("trade_no"));
        paymentInfo.setCallbackTime(new Date());
        paymentInfo.setCallbackContent(paramMap.toString());
        this.updateById(paymentInfo);

        //3.发送MQ消息通知订单服务修改订单状态
        rabbitService.sendMessage(MqConst.EXCHANGE_PAYMENT_PAY, MqConst.ROUTING_PAYMENT_PAY, orderNo);
        //4.发送MQ消息通知商品服务库存扣减
        rabbitService.sendMessage(MqConst.EXCHANGE_PRODUCT, MqConst.ROUTING_MINUS, orderNo);

    }
}
